﻿using System;
using System.Collections.Generic;
using System.Collections;

namespace SharpTag.ID3
{
    /// <summary>
    /// Concrete implementation of the <see cref="ITagHeader"/> interface.
    /// </summary>
    public class ID3V2TagHeader : ITagHeader
    {
        /// <summary>
        /// Class constructor.
        /// </summary>
        public ID3V2TagHeader()
        {
            IsDirty = false;
        }

        /// <summary>
        /// Gets the Identifier of the Tag.
        /// </summary>
        public string Identifier { get; private set; }

        /// <summary>
        /// Gets the Version of the Tag.
        /// </summary>
        public double Version { get; private set; }

        /// <summary>
        /// Gets the Size of the Tag.
        /// </summary>
        public long Size { get; private set; }

        /// <summary>
        /// Gets a list of the of <see cref="TagHeaderFlag"/> objects found in the Tag.
        /// </summary>
        public List<TagHeaderFlag> Flags { get; private set; }

        /// <summary>
        /// Gets whether or not the Header has been modified.
        /// </summary>
        public bool IsDirty { get; private set; }

        /// <summary>
        /// Adds a <see cref="TagHeaderFlag"/> object to the Tag.
        /// </summary>
        /// <param name="flag"></param>
        public void AddFlag(TagHeaderFlag flag)
        {
            if (!Flags.Contains(flag))
            {
                Flags.Add(flag);
                IsDirty = true;
            }
                
        }

        /// <summary>
        /// Removes a <see cref="TagHeaderFlag"/> from the Tag.
        /// </summary>
        /// <param name="flag"></param>
        public void RemoveFlag(TagHeaderFlag flag)
        {
            if (Flags.Contains(flag))
            {
                Flags.Remove(flag);
                IsDirty = true;
            }
                
        }

        /// <summary>
        /// Creates the <see cref="ITagFooter"/> object of the Tag.
        /// </summary>
        /// <returns></returns>
        public ITagFooter CreateFooter()
        {
            //TODO: Implement the CreateFooter method.
            throw new NotImplementedException();
        }

        /// <summary>
        /// Parses the raw header data into the appropriate properties.
        /// </summary>
        /// <param name="headerBytes">A byte array containging the raw header data.</param>
        public void ParseHeaderData(byte[] headerBytes)
        {
            var iden = new char[3];
            var vers = new byte[2];
            var size = new byte[4];

            Array.Copy(headerBytes, 0, iden, 0, 3);
            Array.Copy(headerBytes, 3, vers, 0, 2);
            byte flags = headerBytes[5];
            Array.Copy(headerBytes, 6, size, 0, 4);

            Identifier = new string(iden);
            Version = double.Parse(string.Concat("2.", vers[0]));
            ParseFlags(flags);
            Size = size.CalcualteSyncSafeSize();
        }

        /// <summary>
        /// Helper method to parse the header flag bits from the header flag byte.
        /// </summary>
        /// <param name="flagByte"></param>
        private void ParseFlags(byte flagByte)
        {
            BitArray flags = new BitArray(flagByte);

            for (int i = 0; i < flags.Length; i++)
            {
                if (flags[i])
                {
                    switch (i)
                    {
                        case 0:
                            Flags.Add(TagHeaderFlag.Unsynchronization);
                            break;
                        case 1:
                            Flags.Add(TagHeaderFlag.ExtendedHeader);
                            break;
                        case 2:
                            Flags.Add(TagHeaderFlag.ExperimentalIndicator);
                            break;
                        case 3:
                            Flags.Add(TagHeaderFlag.FooterPresent);
                            break;
                    }
                }
            }
        }

        /// <summary>
        /// Converts the Frame Header data into a byte array to be written out to the physical file.
        /// </summary>
        /// <returns></returns>
        public byte[] PrepareBytes()
        {
            throw new NotImplementedException();
        }
    }
}
